{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from sklearn.datasets import load_digits\n",
    "from sklearn.preprocessing import LabelBinarizer\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import classification_report,confusion_matrix\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1797, 8, 8)\n"
     ]
    }
   ],
   "source": [
    "# 载入数据\n",
    "digits = load_digits()\n",
    "print(digits.images.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nuo92pLZ1pQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a4af0ca550>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\nencmMXrTAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a4b23e3ef0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\nSOw/oBOOxah6/R8AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a4b01e3c88>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 显示图片\n",
    "plt.imshow(digits.images[0],cmap='gray')\n",
    "plt.show()\n",
    "plt.imshow(digits.images[1],cmap='gray')\n",
    "plt.show()\n",
    "plt.imshow(digits.images[2],cmap='gray')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1797, 64)\n",
      "(1797,)\n",
      "[[ 0.  0.  5. 13.  9.  1.  0.  0.  0.  0. 13. 15. 10. 15.  5.  0.  0.  3.\n",
      "  15.  2.  0. 11.  8.  0.  0.  4. 12.  0.  0.  8.  8.  0.  0.  5.  8.  0.\n",
      "   0.  9.  8.  0.  0.  4. 11.  0.  1. 12.  7.  0.  0.  2. 14.  5. 10. 12.\n",
      "   0.  0.  0.  0.  6. 13. 10.  0.  0.  0.]\n",
      " [ 0.  0.  0. 12. 13.  5.  0.  0.  0.  0.  0. 11. 16.  9.  0.  0.  0.  0.\n",
      "   3. 15. 16.  6.  0.  0.  0.  7. 15. 16. 16.  2.  0.  0.  0.  0.  1. 16.\n",
      "  16.  3.  0.  0.  0.  0.  1. 16. 16.  6.  0.  0.  0.  0.  1. 16. 16.  6.\n",
      "   0.  0.  0.  0.  0. 11. 16. 10.  0.  0.]\n",
      " [ 0.  0.  0.  4. 15. 12.  0.  0.  0.  0.  3. 16. 15. 14.  0.  0.  0.  0.\n",
      "   8. 13.  8. 16.  0.  0.  0.  0.  1.  6. 15. 11.  0.  0.  0.  1.  8. 13.\n",
      "  15.  1.  0.  0.  0.  9. 16. 16.  5.  0.  0.  0.  0.  3. 13. 16. 16. 11.\n",
      "   5.  0.  0.  0.  0.  3. 11. 16.  9.  0.]]\n",
      "[0 1 2]\n"
     ]
    }
   ],
   "source": [
    "# 数据\n",
    "X = digits.data\n",
    "# 标签\n",
    "y = digits.target\n",
    "print(X.shape)\n",
    "print(y.shape)\n",
    "print(X[:3])\n",
    "print(y[:3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 5 5 5 1]\n",
      "[[0 1 0 0 0 0 0 0 0 0]\n",
      " [0 0 0 0 0 1 0 0 0 0]\n",
      " [0 0 0 0 0 1 0 0 0 0]\n",
      " [0 0 0 0 0 1 0 0 0 0]\n",
      " [0 1 0 0 0 0 0 0 0 0]]\n"
     ]
    }
   ],
   "source": [
    "# 定义一个神经网络，结构：64-100-10\n",
    "# 定义输入层到隐藏层之间的权值矩阵\n",
    "V = np.random.random((64,100))*2-1\n",
    "# 定义隐藏层到输出层之间的权值矩阵\n",
    "W = np.random.random((100,10))*2-1\n",
    "\n",
    "# 数据切分\n",
    "# 1/4为测试集，3/4为训练集\n",
    "X_train,X_test,y_train,y_test = train_test_split(X,y)\n",
    "\n",
    "# 标签二值化 \n",
    "# 0->1000000000\n",
    "# 3->0001000000\n",
    "# 9->0000000001\n",
    "labels_train = LabelBinarizer().fit_transform(y_train)\n",
    "print(y_train[:5])\n",
    "print(labels_train[:5])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 激活函数\n",
    "def sigmoid(x):\n",
    "    return 1/(1+np.exp(-x))\n",
    "\n",
    "# 激活函数的导数\n",
    "def dsigmoid(x):\n",
    "    return x*(1-x)\n",
    "\n",
    "# 训练模型\n",
    "def train(X,y,steps=10000,lr=0.11):\n",
    "    global V,W\n",
    "    for n in range(steps+1):\n",
    "        # 随机选取一个数据\n",
    "        i = np.random.randint(X.shape[0])\n",
    "        # 获取一个数据\n",
    "        x = X[i]\n",
    "        x = np.atleast_2d(x)\n",
    "        # BP算法公式\n",
    "        # 计算隐藏层的输出\n",
    "        L1 = sigmoid(np.dot(x,V))\n",
    "        # 计算输出的输出\n",
    "        L2 = sigmoid(np.dot(L1,W))\n",
    "        # 计算L2_delta，L1_delta\n",
    "        L2_delta = (y[i]-L2)*dsigmoid(L2)\n",
    "        L1_delta = L2_delta.dot(W.T)*dsigmoid(L1)\n",
    "        # 更新权值\n",
    "        W += lr*L1.T.dot(L2_delta)\n",
    "        V += lr*x.T.dot(L1_delta)\n",
    "        \n",
    "        # 每训练1000次预测一次准确率\n",
    "        if n%1000==0:\n",
    "            output = predict(X_test)\n",
    "            predictions = np.argmax(output,axis=1)\n",
    "            acc = np.mean(np.equal(predictions,y_test))\n",
    "            print('steps:',n,'accuracy:',acc)\n",
    "\n",
    "def predict(x):\n",
    "    # 计算隐藏层的输出\n",
    "    L1 = sigmoid(np.dot(x,V))\n",
    "    # 计算输出的输出\n",
    "    L2 = sigmoid(np.dot(L1,W))\n",
    "    return L2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "steps: 0 accuracy: 0.08444444444444445\n",
      "steps: 1000 accuracy: 0.52\n",
      "steps: 2000 accuracy: 0.64\n",
      "steps: 3000 accuracy: 0.7222222222222222\n",
      "steps: 4000 accuracy: 0.7955555555555556\n",
      "steps: 5000 accuracy: 0.8266666666666667\n",
      "steps: 6000 accuracy: 0.84\n",
      "steps: 7000 accuracy: 0.8444444444444444\n",
      "steps: 8000 accuracy: 0.8555555555555555\n",
      "steps: 9000 accuracy: 0.8577777777777778\n",
      "steps: 10000 accuracy: 0.9488888888888889\n",
      "steps: 11000 accuracy: 0.94\n",
      "steps: 12000 accuracy: 0.9444444444444444\n",
      "steps: 13000 accuracy: 0.9622222222222222\n",
      "steps: 14000 accuracy: 0.9755555555555555\n",
      "steps: 15000 accuracy: 0.9511111111111111\n",
      "steps: 16000 accuracy: 0.9688888888888889\n",
      "steps: 17000 accuracy: 0.9711111111111111\n",
      "steps: 18000 accuracy: 0.9688888888888889\n",
      "steps: 19000 accuracy: 0.9755555555555555\n",
      "steps: 20000 accuracy: 0.9688888888888889\n",
      "steps: 21000 accuracy: 0.9622222222222222\n",
      "steps: 22000 accuracy: 0.9666666666666667\n",
      "steps: 23000 accuracy: 0.9688888888888889\n",
      "steps: 24000 accuracy: 0.9755555555555555\n",
      "steps: 25000 accuracy: 0.9733333333333334\n",
      "steps: 26000 accuracy: 0.9733333333333334\n",
      "steps: 27000 accuracy: 0.98\n",
      "steps: 28000 accuracy: 0.9711111111111111\n",
      "steps: 29000 accuracy: 0.9644444444444444\n",
      "steps: 30000 accuracy: 0.98\n"
     ]
    }
   ],
   "source": [
    "train(X_train,labels_train,30000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             precision    recall  f1-score   support\n",
      "\n",
      "          0       1.00      1.00      1.00        43\n",
      "          1       1.00      0.94      0.97        48\n",
      "          2       1.00      0.98      0.99        54\n",
      "          3       0.95      0.98      0.97        43\n",
      "          4       0.96      1.00      0.98        43\n",
      "          5       1.00      0.98      0.99        48\n",
      "          6       1.00      0.98      0.99        41\n",
      "          7       1.00      0.98      0.99        53\n",
      "          8       0.89      0.98      0.93        43\n",
      "          9       1.00      1.00      1.00        34\n",
      "\n",
      "avg / total       0.98      0.98      0.98       450\n",
      "\n"
     ]
    }
   ],
   "source": [
    "output = predict(X_test)\n",
    "predictions = np.argmax(output,axis=1)\n",
    "print(classification_report(predictions,y_test))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[43  0  0  0  0  0  0  0  0  0]\n",
      " [ 0 45  0  0  1  0  0  0  2  0]\n",
      " [ 0  0 53  0  0  0  0  0  1  0]\n",
      " [ 0  0  0 42  0  0  0  0  1  0]\n",
      " [ 0  0  0  0 43  0  0  0  0  0]\n",
      " [ 0  0  0  1  0 47  0  0  0  0]\n",
      " [ 0  0  0  0  0  0 40  0  1  0]\n",
      " [ 0  0  0  1  0  0  0 52  0  0]\n",
      " [ 0  0  0  0  1  0  0  0 42  0]\n",
      " [ 0  0  0  0  0  0  0  0  0 34]]\n"
     ]
    }
   ],
   "source": [
    "print(confusion_matrix(predictions,y_test))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
